//! 哈希映射(HashMap)示例
//!
//! HashMap<K, V> 是一种键值对存储的数据结构，可以通过键快速获取值。

use std::collections::HashMap;

/// 创建哈希映射
pub fn creating_hashmaps() {
    // 创建一个新的空 HashMap
    let mut scores = HashMap::new();

    // 插入键值对
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    println!("创建哈希映射:");
    println!("scores: {:?}", scores);

    // 使用迭代器和 collect 方法创建 HashMap
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];

    let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

    println!("使用迭代器创建:");
    println!("scores: {:?}", scores);

    // 使用一个元组的vector的collect 方法构建map
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];
    // 使用zip方法来创建一个元组的vector，zip方法返回一个新的迭代器，该迭代器将迭代其他两个迭代器，返回一个元组
    let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();
    println!("使用zip创建的scores: {:?}", scores);
    for (key, value) in &scores {
        println!("key->{}:value->{}", key, value);
    }
}

/// 访问哈希映射中的值
pub fn accessing_values() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    // 使用 get 方法获取值
    let team_name = String::from("Blue");
    let score = scores.get(&team_name);

    println!("访问哈希映射中的值:");
    match score {
        Some(s) => println!("Blue 队得分: {}", s),
        None => println!("没有找到 Blue 队"),
    }

    // 遍历键值对
    println!("遍历所有键值对:");
    for (key, value) in &scores {
        println!("{}: {}", key, value);
    }

    // 新建/覆盖map
    let mut map = HashMap::new();
    map.insert(1, 2);
    println!("新建/覆盖map: {:?}", map);
}

/// 更新哈希映射
pub fn updating_hashmaps() {
    let mut scores = HashMap::new();

    // 覆盖已存在的值
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 25);

    println!("覆盖已存在的值:");
    println!("Blue 队得分: {:?}", scores.get("Blue"));

    // 只在键不存在时插入
    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);

    println!("使用 entry API:");
    println!("scores: {:?}", scores);

    // 只在键没有对应值时插入
    let mut map = HashMap::new();
    map.insert(1, 2);
    map.entry(1).or_insert(50);
    println!("只在键没有对应值时插入: {:?}", map);
}

/// 基于旧值更新
pub fn update_based_on_old_value() {
    let text = "hello world wonderful world";
    let mut map = HashMap::new();

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }

    println!("基于旧值更新:");
    println!("词频统计: {:?}", map);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_creating_hashmaps() {
        creating_hashmaps();
    }

    #[test]
    fn test_accessing_values() {
        accessing_values();
    }

    #[test]
    fn test_updating_hashmaps() {
        updating_hashmaps();
    }

    #[test]
    fn test_update_based_on_old_value() {
        update_based_on_old_value();
    }
}
